{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 课程内容\n",
    "\n",
    "本课利用百度人脸识别应用、百度语音合成技术进行人脸识别和语音播报。\n",
    "\n",
    "本课引入多任务的概念，利用我们的多核处理器，让树莓派动起来，让显示更流畅。\n",
    "\n",
    "百度百科: 多任务处理是指系统可同时运行多个进程，而每个进程也可同时执行多个线程。一个线程是指程序的一条执行路径，它在系统指定的时间片中完成特定的功能。系统不停地在多个线程之间切换，由于时间很短，看上去多个线程在同时运行。或者对于在线程序可并行执行同时服务于多个用户称为多任务处理。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 开始我们的实验\n",
    "\n",
    "## (1)认识多任务\n",
    "我们之前的程序为\n",
    "\n",
    "    if __name__ == \"__main__\":\n",
    "        try:\n",
    "            while True:\n",
    "                程序主体\n",
    "\n",
    "        except KeyboardInterrupt:  \n",
    "            程序退出处理\n",
    "\n",
    "我们的程序一直在\"while True\"里不断地执行，对于简单任务来说，这样的程序能满足需要，但对于稍微复杂点的程序，这样的设计就不能满足我们的需求了。\n",
    "\n",
    "例如:上节课的程序，我们获取图像，发送百度AI进行分析，然后显示处理结果；在进行分析和显示处理结果时，读取图像的功能就没有执行。\n",
    "\n",
    "我们想要的效果就是，在读取图像进行显示的同时，进行图像进行百度AI分析，同时进行其他的一些操作(例如，本课的语音提示戴口罩)。如何来实现我们的想法呢?\n",
    "\n",
    "我们需要引入多任务。\n",
    "\n",
    "python的多任务库为:from multiprocessing import Process, Queue\n",
    "其中Process为多任务的模块，Queue为多任务通信的消息队列机制。\n",
    "\n",
    "如何使用多任务？就两步。\n",
    "\n",
    "①建立多任务。\n",
    "\n",
    "    建立一个多任务\n",
    "    get_camera_frame = Process(target=camera_frame_func, args=(\"获取摄像头图像\", q_frame, mydict))\n",
    "    参数:target为该任务的处理函数\n",
    "    参数:args为处理函数的参数，\"获取摄像头图像\"为该任务的名称；q_frame为传递给该任务的第一个参数；mydict为传递给该任务的第二个参数。\n",
    "    target为该任务的处理函数的格式:\n",
    "    #　获取摄像头图像\n",
    "    def camera_frame_func(task_name, mult_queue1, mydict):  \n",
    "        #　给出提示信息\n",
    "        \n",
    "        print(task_name + \"任务启动\")\n",
    "        try:\n",
    "            while True:\n",
    "                #添加自己的函数处理模块\n",
    "  \n",
    "        except KeyboardInterrupt:\n",
    "            #程序退出处理\n",
    "     \n",
    "    返回值:get_camera_frame为该任务的处理对象。   \n",
    "    发现没有，处理函数的格式就是我们之前的程序。\n",
    "\n",
    "②启动该任务\n",
    "    \n",
    "    #启动get_camera_frame任务\n",
    "    get_camera_frame.start()\n",
    "    只需要调用get_camera_frame对象的start方法就可以启动该任务。\n",
    "    \n",
    "这样启动了多任后，例如我们建立了4个任务，操作系统会按照相应的调度策略让任务进行运行，对于我们所使用的树莓派4B平台，有4个处理器核，每个核上可以运行一个任务，操作系统会调度合适的任务到一个核上处理，这样就做到的真正的同时运行程序的效果。\n",
    "\n",
    "## (２)任务间通信(进程间通信)\n",
    "我们的启动后，都在各自执行各自的工作，但他们没有交互，我该如何将任务1读取到的图像传递给任务2进行百度AI分析呢?\n",
    "这时，我们需要引入任务间通信，本次我们使用消息队列的方式。\n",
    "\n",
    "python的多任务库为:from multiprocessing import Process, Queue\n",
    "其中Process为多任务的模块，Queue为多任务通信的消息队列机制。\n",
    "\n",
    "我们该如何使用消息队列呢?\n",
    "\n",
    "如何使用多任务？就三步。\n",
    "\n",
    "①建立一个消息队列\n",
    "\n",
    "    q_frame = Queue()\n",
    "    q_frame就是一个消息队列的对象，我们使用这个他就行了。\n",
    "    \n",
    "②传递消息队列到进程\n",
    "\n",
    "    Process(target=camera_frame_func, args=(\"获取摄像头图像\", q_frame))\n",
    "    在进程参数中添加该消息队列，就可以将消息队列传递给该进程\n",
    "    \n",
    "③向消息队列发送消息或者从消息队列读取消息\n",
    "\n",
    "    向消息队列发送数据:\n",
    "    mult_queue1.put(frame) \n",
    "    调用消息队列的put方法，就将frame对象的数据放到消息队列中\n",
    "    \n",
    "    从消息队列读取数据:\n",
    "    frame = mult_queue.get()\n",
    "    调用消息队列的get方法，就将取出的对象放在frame中（准确的说是frame指向该对象）。\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "######################################################\n",
    "#\n",
    "# 先感受下小派的口罩检测，带好口罩，挡住病毒,选择本cell，按shirt+enter键运行本模块\n",
    "#\n",
    "######################################################\n",
    "#!/usr/bin/env python\n",
    "# -*- coding: utf-8 -*-\n",
    "#\n",
    "# Copyright (c) 2020 Taste all Pi.\n",
    "#\n",
    "# Licensed under the GNU General Public License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "#   http://www.gnu.org/licenses/gpl-2.0.html\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License.\n",
    "\n",
    "#导入标准库\n",
    "import sys\n",
    "import os\n",
    "from playsound import playsound\n",
    "import cv2 as cv\n",
    "import time\n",
    "from multiprocessing import Process, Queue\n",
    "import multiprocessing\n",
    "\n",
    "#导入自定义库\n",
    "sys.path.append('../baidu_api_lib')\n",
    "from baidu_picture import baidu_picture_2_msg\n",
    "from baidu_sound import baidu_word_2_sound\n",
    "\n",
    "\"\"\" 公开课语音合成+人脸识别，可选更改为自己的api接口 \"\"\"\n",
    "APP_ID = '21139072'\n",
    "API_KEY = 'tZ0j3YspNiGDhLeO7vxxvdzb'\n",
    "SECRET_KEY = 'UaaaMyO8RiZvXj0HxEt9DQavuk6u2uA3'\n",
    "\n",
    "#百度AI的调用url\n",
    "baidu_request_url = \"https://aip.baidubce.com/rest/2.0/face/v3/detect\"\n",
    "\n",
    "#处理图像的频率\n",
    "FRAME_PROC_FR = 80\n",
    "\n",
    "#　获取摄像头图像\n",
    "def camera_frame_func(task_name, mult_queue1, mydict):\n",
    "    \n",
    "    # 创建一个VideoCapture对象\n",
    "    capture = cv.VideoCapture(0)   \n",
    "    \n",
    "    #　给出提示信息\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    #　传递视频的周期\n",
    "    pic_hz = 0\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            # 一帧一帧读取视频\n",
    "            ret, frame = capture.read()\n",
    "            \n",
    "            #　将图像发送至队列中\n",
    "            pic_hz+=1\n",
    "            if (pic_hz % FRAME_PROC_FR) == 1:     \n",
    "                mult_queue1.put(frame) \n",
    "            \n",
    "            #获取人脸位置\n",
    "            if mydict:   \n",
    "                #获取脸的个数\n",
    "                face_num = mydict[\"result\"][\"face_num\"]\n",
    "                \n",
    "                #有人脸才进行画框\n",
    "                if face_num:\n",
    "                    #获取人脸位置，画出图框\n",
    "                    for i in range(face_num):\n",
    "                        location = mydict[\"result\"][\"face_list\"][i][\"location\"]\n",
    "                        left_top = (int(location['left']), int(location['top']))\n",
    "                        right_bottom = (int(left_top[0] + location['width']), int(left_top[1] + location['height']))\n",
    "                        cv.rectangle(frame, left_top, right_bottom, (0,255,0),2) \n",
    "            \n",
    "            # 本地显示视频图像\n",
    "            cv.imshow('capture', frame) \n",
    "            cv.waitKey(1)\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        # 释放cap,销毁窗口\n",
    "        capture.release()      \n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#处理图像\n",
    "def proc_frame_func(task_name, mult_queue, mult_queue2, mydict):\n",
    "    #　给出提示信息\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    # 传入百度AI的参数\n",
    "    pic_msg = baidu_picture_2_msg(APP_ID, API_KEY, SECRET_KEY)\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            #从队列中获取图片\n",
    "            frame = mult_queue.get()\n",
    "            \n",
    "            # 写入图片\n",
    "            cv.imwrite('camera_pic.jpg',frame) \n",
    "            \n",
    "            #从百度AI获取图片分析结果\n",
    "            response = pic_msg.pic_2_msg(baidu_request_url, 'camera_pic.jpg')\n",
    "            \n",
    "            #获取分析数据是否正确\n",
    "            error_msg = response.json()[\"error_msg\"]\n",
    "            \n",
    "            #获取到正确信息\n",
    "            if error_msg == 'SUCCESS': \n",
    "                #更新人脸识别信息\n",
    "                mydict[\"result\"] = response.json()[\"result\"]\n",
    "            \n",
    "            #将播报信息进行对外发送\n",
    "            mult_queue2.put(response) \n",
    "            \n",
    "    except KeyboardInterrupt:\n",
    "        os.remove('camera_pic.jpg')\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#播报语音信息\n",
    "def read_rst_func(task_name, mult_queue):\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    #传入百度AI的参数\n",
    "    word_2_sound = baidu_word_2_sound(APP_ID, API_KEY, SECRET_KEY)\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            #从队列中获取播报信息\n",
    "            response = mult_queue.get()\n",
    "            \n",
    "            #获取分析数据是否正确\n",
    "            error_msg = response.json()[\"error_msg\"]\n",
    "            \n",
    "            #获取到正确信息\n",
    "            if error_msg == 'SUCCESS':   \n",
    "                #获取脸的个数\n",
    "                face_num = response.json()[\"result\"][\"face_num\"]\n",
    "\n",
    "                #置戴口罩标记为戴口罩了\n",
    "                mask_valid = 1\n",
    "\n",
    "                #获取人脸位置，画出图框\n",
    "                for i in range(face_num):\n",
    "                    mask_data = response.json()[\"result\"][\"face_list\"][i][\"mask\"][\"type\"]\n",
    "\n",
    "                    #发现没带口罩\n",
    "                    if mask_data == 0:\n",
    "                        mask_valid = 0\n",
    "\n",
    "                if mask_valid == 0:        \n",
    "                    #发现没带口罩，则播报提示\n",
    "                    word_2_sound.trans_word_to_sound(\"请正确佩戴口罩\",'tst_sound.wav')\n",
    "                    os.system('mplayer ' + 'tst_sound.wav')\n",
    "        \n",
    "    except KeyboardInterrupt:\n",
    "        os.remove('tst_sound.wav')\n",
    "        print(task_name + \"任务被终止\")\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    try:\n",
    "        \n",
    "        mydict=multiprocessing.Manager().dict()\n",
    "        \n",
    "        #　定义传递图像队列和传递图像处理结果队列\n",
    "        q_frame = Queue()\n",
    "        q_respond = Queue()\n",
    "        \n",
    "        #　采集摄像头进程、处理图片进程、播报语音信息\n",
    "        get_camera_frame = Process(target=camera_frame_func, args=(\"获取摄像头图像\", q_frame, mydict))\n",
    "        proc_frame       = Process(target=proc_frame_func, args=(\"处理图像\", q_frame, q_respond, mydict))\n",
    "        read_rst         = Process(target=read_rst_func, args=(\"播报语音信息\", q_respond))\n",
    "              \n",
    "        # 启动任务\n",
    "        get_camera_frame.start()\n",
    "        proc_frame.start()\n",
    "        read_rst.start()\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        os.remove('tst_sound.wav')\n",
    "        os.remove('camera_pic.jpg')\n",
    "        print(\"任务被终止了\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 让我们临摹代码，学习“口罩”功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# #导入标准库\n",
    "# import sys\n",
    "\n",
    "# import os\n",
    "\n",
    "# from playsound import playsound\n",
    "\n",
    "# import cv2 as cv\n",
    "\n",
    "# import time\n",
    "\n",
    "# from multiprocessing import Process, Queue\n",
    "\n",
    "# import multiprocessing\n",
    "\n",
    "\n",
    "# #导入自定义库\n",
    "# sys.path.append('../baidu_api_lib')\n",
    "\n",
    "# from baidu_picture import baidu_picture_2_msg\n",
    "\n",
    "# from baidu_sound import baidu_word_2_sound\n",
    "\n",
    "\n",
    "# \"\"\" 公开课语音合成+人脸识别，可选更改为自己的api接口 \"\"\"\n",
    "# APP_ID = '21139072'\n",
    "\n",
    "# API_KEY = 'tZ0j3YspNiGDhLeO7vxxvdzb'\n",
    "\n",
    "# SECRET_KEY = 'UaaaMyO8RiZvXj0HxEt9DQavuk6u2uA3'\n",
    "\n",
    "\n",
    "# #百度AI的调用url\n",
    "# baidu_request_url = \"https://aip.baidubce.com/rest/2.0/face/v3/detect\"\n",
    "\n",
    "\n",
    "# #处理图像的频率\n",
    "# FRAME_PROC_FR = 80\n",
    "\n",
    "\n",
    "# #　获取摄像头图像\n",
    "# def camera_frame_func(task_name, mult_queue1, mydict):\n",
    "\n",
    "    \n",
    "#     # 创建一个VideoCapture对象\n",
    "#     capture = cv.VideoCapture(0)   \n",
    "\n",
    "    \n",
    "#     #　给出提示信息\n",
    "#     print(task_name + \"任务启动\")\n",
    "\n",
    "    \n",
    "#     #　传递视频的周期\n",
    "#     pic_hz = 0\n",
    "\n",
    "    \n",
    "#     try:\n",
    "\n",
    "#         while True:\n",
    "\n",
    "#             # 一帧一帧读取视频\n",
    "#             ret, frame = capture.read()\n",
    "\n",
    "            \n",
    "#             #　将图像发送至队列中\n",
    "#             pic_hz+=1\n",
    "\n",
    "#             if (pic_hz % FRAME_PROC_FR) == 1:   \n",
    "\n",
    "#                 mult_queue1.put(frame) \n",
    "\n",
    "            \n",
    "#             #获取人脸位置\n",
    "#             if mydict:   \n",
    "\n",
    "#                 #获取脸的个数\n",
    "#                 face_num = mydict[\"result\"][\"face_num\"]\n",
    "\n",
    "                \n",
    "#                 #有人脸才进行画框\n",
    "#                 if face_num:\n",
    "\n",
    "#                     #获取人脸位置，画出图框\n",
    "#                     for i in range(face_num):\n",
    "\n",
    "#                         location = mydict[\"result\"][\"face_list\"][i][\"location\"]\n",
    "\n",
    "#                         left_top = (int(location['left']), int(location['top']))\n",
    "\n",
    "#                         right_bottom = (int(left_top[0] + location['width']), int(left_top[1] + location['height']))\n",
    "\n",
    "#                         cv.rectangle(frame, left_top, right_bottom, (0,255,0),2) \n",
    "\n",
    "            \n",
    "#             # 本地显示视频图像\n",
    "#             cv.imshow('capture', frame)\n",
    "\n",
    "#             cv.waitKey(1)\n",
    "\n",
    "\n",
    "#     except KeyboardInterrupt:\n",
    "\n",
    "#         # 释放cap,销毁窗口\n",
    "#         capture.release()     \n",
    "\n",
    "#         print(task_name + \"任务被终止\")\n",
    "\n",
    "        \n",
    "# #处理图像\n",
    "# def proc_frame_func(task_name, mult_queue, mult_queue2, mydict):\n",
    "\n",
    "#     #　给出提示信息\n",
    "#     print(task_name + \"任务启动\")\n",
    "\n",
    "    \n",
    "#     # 传入百度AI的参数\n",
    "#     pic_msg = baidu_picture_2_msg(APP_ID, API_KEY, SECRET_KEY)\n",
    "\n",
    "    \n",
    "#     try:\n",
    "\n",
    "#         while True:\n",
    "\n",
    "#             #从队列中获取图片\n",
    "#             frame = mult_queue.get()\n",
    "\n",
    "            \n",
    "#             # 写入图片\n",
    "#             cv.imwrite('camera_pic.jpg',frame) \n",
    "\n",
    "            \n",
    "#             #从百度AI获取图片分析结果\n",
    "#             response = pic_msg.pic_2_msg(baidu_request_url, 'camera_pic.jpg')\n",
    "\n",
    "            \n",
    "#             #获取分析数据是否正确\n",
    "#             error_msg = response.json()[\"error_msg\"]\n",
    "\n",
    "            \n",
    "#             #获取到正确信息\n",
    "#             if error_msg == 'SUCCESS': \n",
    "\n",
    "#                 #更新人脸识别信息\n",
    "#                 mydict[\"result\"] = response.json()[\"result\"]\n",
    "\n",
    "            \n",
    "#             #将播报信息进行对外发送\n",
    "#             mult_queue2.put(response) \n",
    "\n",
    "            \n",
    "#     except KeyboardInterrupt:\n",
    "\n",
    "#         os.remove('camera_pic.jpg')\n",
    "\n",
    "#         print(task_name + \"任务被终止\")\n",
    "\n",
    "        \n",
    "# #播报语音信息\n",
    "# def read_rst_func(task_name, mult_queue):\n",
    "\n",
    "#     print(task_name + \"任务启动\")\n",
    "\n",
    "    \n",
    "#     #传入百度AI的参数\n",
    "#     word_2_sound = baidu_word_2_sound(APP_ID, API_KEY, SECRET_KEY)\n",
    "\n",
    "    \n",
    "#     try:\n",
    "\n",
    "#         while True:\n",
    "\n",
    "#             #从队列中获取播报信息\n",
    "#             response = mult_queue.get()\n",
    "\n",
    "            \n",
    "#             #获取分析数据是否正确\n",
    "#             error_msg = response.json()[\"error_msg\"]\n",
    "\n",
    "            \n",
    "#             #获取到正确信息\n",
    "#             if error_msg == 'SUCCESS':   \n",
    "\n",
    "#                 #获取脸的个数\n",
    "#                 face_num = response.json()[\"result\"][\"face_num\"]\n",
    "\n",
    "\n",
    "#                 #置戴口罩标记为戴口罩了\n",
    "#                 mask_valid = 1\n",
    "\n",
    "\n",
    "#                 #获取人脸位置，画出图框\n",
    "#                 for i in range(face_num):\n",
    "\n",
    "#                     mask_data = response.json()[\"result\"][\"face_list\"][i][\"mask\"][\"type\"]\n",
    "\n",
    "\n",
    "#                     #发现没带口罩\n",
    "#                     if mask_data == 0:\n",
    "\n",
    "#                         mask_valid = 0\n",
    "\n",
    "\n",
    "#                 if mask_valid == 0:     \n",
    "\n",
    "#                     #发现没带口罩，则播报提示\n",
    "#                     word_2_sound.trans_word_to_sound(\"请正确佩戴口罩\",'tst_sound.wav')\n",
    "\n",
    "#                     os.system('mplayer ' + 'tst_sound.wav')\n",
    "\n",
    "        \n",
    "#     except KeyboardInterrupt:\n",
    "\n",
    "#         os.remove('tst_sound.wav')\n",
    "\n",
    "#         print(task_name + \"任务被终止\")\n",
    "\n",
    "\n",
    "# if __name__ == \"__main__\":\n",
    "\n",
    "#     try:\n",
    "\n",
    "        \n",
    "#         mydict=multiprocessing.Manager().dict()\n",
    "\n",
    "        \n",
    "#         #　定义传递图像队列和传递图像处理结果队列\n",
    "#         q_frame = Queue()\n",
    "\n",
    "#         q_respond = Queue()\n",
    "\n",
    "        \n",
    "#         #　采集摄像头进程、处理图片进程、播报语音信息\n",
    "#         get_camera_frame = Process(target=camera_frame_func, args=(\"获取摄像头图像\", q_frame, mydict))\n",
    "\n",
    "#         proc_frame       = Process(target=proc_frame_func, args=(\"处理图像\", q_frame, q_respond, mydict))\n",
    "\n",
    "#         read_rst         = Process(target=read_rst_func, args=(\"播报语音信息\", q_respond))\n",
    "\n",
    "              \n",
    "#         # 启动任务\n",
    "#         get_camera_frame.start()\n",
    "\n",
    "#         proc_frame.start()\n",
    "\n",
    "#         read_rst.start()\n",
    "\n",
    "\n",
    "#     except KeyboardInterrupt:\n",
    "\n",
    "#         os.remove('tst_sound.wav')\n",
    "\n",
    "#         os.remove('camera_pic.jpg')\n",
    "\n",
    "#         print(\"任务被终止了\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 课后练习\n",
    "１、我们的人脸识别同时带有情绪检测，做一个情绪互动小游戏把。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#!/usr/bin/env python\n",
    "# -*- coding: utf-8 -*-\n",
    "#\n",
    "# Copyright (c) 2020 Taste all Pi.\n",
    "#\n",
    "# Licensed under the GNU General Public License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "#   http://www.gnu.org/licenses/gpl-2.0.html\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License.\n",
    "\n",
    "#导入标准库\n",
    "import sys\n",
    "import os\n",
    "from playsound import playsound\n",
    "import cv2 as cv\n",
    "import time\n",
    "from multiprocessing import Process, Queue\n",
    "import multiprocessing\n",
    "import random\n",
    "\n",
    "#导入自定义库\n",
    "sys.path.append('../baidu_api_lib')\n",
    "from baidu_picture import baidu_picture_2_msg\n",
    "from baidu_sound import baidu_word_2_sound\n",
    "\n",
    "\"\"\" 公开课语音合成+人脸识别，可选更改为自己的api接口 \"\"\"\n",
    "APP_ID = '21139072'\n",
    "API_KEY = 'tZ0j3YspNiGDhLeO7vxxvdzb'\n",
    "SECRET_KEY = 'UaaaMyO8RiZvXj0HxEt9DQavuk6u2uA3'\n",
    "\n",
    "#百度AI的调用url\n",
    "baidu_request_url = \"https://aip.baidubce.com/rest/2.0/face/v3/detect\"\n",
    "\n",
    "#处理图像的频率\n",
    "FRAME_PROC_FR = 260\n",
    "\n",
    "#情绪列表\n",
    "emotion = {\"angry\":\"愤怒\", \"disgust\":\"厌恶\", \"fear\":\"恐惧\", \"happy\":\"高兴\", \"sad\":\"伤心\",\"surprise\":\"惊讶\",\"neutral\":\"无表情\", \"pouty\":\"撅嘴\", \"grimace\":\"鬼脸\"}\n",
    "\n",
    "#　获取摄像头图像\n",
    "def camera_frame_func(task_name, mult_queue1, mydict):\n",
    "    \n",
    "    # 创建一个VideoCapture对象\n",
    "    capture = cv.VideoCapture(0)   \n",
    "    \n",
    "    #　给出提示信息\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    #　传递视频的周期\n",
    "    pic_hz = 0\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            # 一帧一帧读取视频\n",
    "            ret, frame = capture.read()\n",
    "            \n",
    "            #　将图像发送至队列中\n",
    "            pic_hz+=1\n",
    "            if (pic_hz % FRAME_PROC_FR) == 1:     \n",
    "                mult_queue1.put(frame) \n",
    "            \n",
    "            #获取人脸位置\n",
    "            if mydict:   \n",
    "                #获取脸的个数\n",
    "                face_num = mydict[\"result\"][\"face_num\"]\n",
    "\n",
    "                #获取人脸位置，画出图框\n",
    "                for i in range(face_num):\n",
    "                    location = mydict[\"result\"][\"face_list\"][i][\"location\"]\n",
    "                    left_top = (int(location['left']), int(location['top']))\n",
    "                    right_bottom = (int(left_top[0] + location['width']), int(left_top[1] + location['height']))\n",
    "                    cv.rectangle(frame, left_top, right_bottom, (0,255,0),2) \n",
    "            \n",
    "            # 本地显示视频图像\n",
    "            cv.imshow('capture', frame) \n",
    "            cv.waitKey(1)\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        # 释放cap,销毁窗口\n",
    "        capture.release()      \n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#处理图像\n",
    "def proc_frame_func(task_name, mult_queue, mult_queue2, mydict):\n",
    "    #　给出提示信息\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    # 传入百度AI的参数\n",
    "    pic_msg = baidu_picture_2_msg(APP_ID, API_KEY, SECRET_KEY)\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            #从队列中获取图片\n",
    "            frame = mult_queue.get()\n",
    "            \n",
    "            # 写入图片\n",
    "            cv.imwrite('camera_pic.jpg',frame) \n",
    "            \n",
    "            #从百度AI获取图片分析结果\n",
    "            response = pic_msg.pic_2_msg(baidu_request_url, 'camera_pic.jpg')\n",
    "            \n",
    "            #获取分析数据是否正确\n",
    "            error_msg = response.json()[\"error_msg\"]\n",
    "            \n",
    "            #获取到正确信息\n",
    "            if error_msg == 'SUCCESS':\n",
    "                #更新人脸识别信息\n",
    "                mydict[\"result\"] = response.json()[\"result\"]\n",
    "            \n",
    "            #将播报信息进行对外发送\n",
    "            mult_queue2.put(response) \n",
    "            \n",
    "    except KeyboardInterrupt:\n",
    "        os.remove('camera_pic.jpg')\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#播报语音信息\n",
    "def read_rst_func(task_name, mult_queue):\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    #传入百度AI的参数\n",
    "    word_2_sound = baidu_word_2_sound(APP_ID, API_KEY, SECRET_KEY)\n",
    "    \n",
    "    emotion_key = \"happy\"\n",
    "    print(emotion[emotion_key])\n",
    "    \n",
    "    #发现没带口罩，则播报提示\n",
    "    word_2_sound.trans_word_to_sound(\"我们做个游戏吧，我说表情，你来做\",'tst_sound.mp3')\n",
    "    os.system('mplayer ' + 'tst_sound.mp3')\n",
    "    word_2_sound.trans_word_to_sound(\"请做出一个\"+emotion[emotion_key]+\"的表情\",'tst_sound.mp3')\n",
    "    os.system('mplayer ' + 'tst_sound.mp3')\n",
    "    \n",
    "    #表情做错次数\n",
    "    emotion_err_times = 0\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            #从队列中获取播报信息\n",
    "            response = mult_queue.get()\n",
    "            \n",
    "            #获取分析数据是否正确\n",
    "            error_msg = response.json()[\"error_msg\"]\n",
    "            \n",
    "            #获取到正确信息\n",
    "            if error_msg == 'SUCCESS':    \n",
    "                #获取脸的个数\n",
    "                face_num = response.json()[\"result\"][\"face_num\"]\n",
    "\n",
    "                #获取表情信息，进行判断\n",
    "                for i in range(face_num):\n",
    "                    emotion_value = response.json()[\"result\"][\"face_list\"][i][\"emotion\"][\"type\"]\n",
    "\n",
    "                    #表情做的不对\n",
    "                    if emotion_value != emotion_key:\n",
    "                        word_2_sound.trans_word_to_sound(\"我要\"+emotion[emotion_key]+\",不是\"+emotion[emotion_value]+\"的表情\",'tst_sound.wav')\n",
    "                        os.system('mplayer ' + 'tst_sound.wav')\n",
    "                        \n",
    "                        #5次未作对，换一个表情\n",
    "                        emotion_err_times += 1\n",
    "                        if emotion_err_times >= 5:\n",
    "                            #随机选择一个表情\n",
    "                            for c in emotion.keys():\n",
    "                                a = random.sample(emotion.keys(), 1)  \n",
    "                                emotion_key = a[0]\n",
    "\n",
    "                            word_2_sound.trans_word_to_sound(\"这个表情好难做啊,我们换一个\"+emotion[emotion_key]+\"的表情\",'tst_sound.wav')\n",
    "                            os.system('mplayer ' + 'tst_sound.wav')\n",
    "                            \n",
    "                            #清零做错次数\n",
    "                            emotion_err_times = 0\n",
    "                    #表情做对的了，换一个表情\n",
    "                    else:     \n",
    "                        #随机选择一个表情\n",
    "                        for c in emotion.keys():\n",
    "                            a = random.sample(emotion.keys(), 1)  \n",
    "                            emotion_key = a[0]\n",
    "\n",
    "                        word_2_sound.trans_word_to_sound(\"你做对了,再做一个\"+emotion[emotion_key]+\"的表情\",'tst_sound.wav')\n",
    "                        os.system('mplayer ' + 'tst_sound.wav')\n",
    "                        \n",
    "            else:\n",
    "                word_2_sound.trans_word_to_sound(\"你去哪了，找不到你了\",'tst_sound.wav')\n",
    "                os.system('mplayer ' + 'tst_sound.wav')\n",
    "                    \n",
    "                    \n",
    "    except KeyboardInterrupt:\n",
    "        os.remove('tst_sound.wav')\n",
    "        print(task_name + \"任务被终止\")\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    try:\n",
    "        \n",
    "        mydict=multiprocessing.Manager().dict()\n",
    "        \n",
    "        #　定义传递图像队列和传递图像处理结果队列\n",
    "        q_frame = Queue()\n",
    "        q_respond = Queue()\n",
    "        \n",
    "        #　采集摄像头进程、处理图片进程、播报语音信息\n",
    "        get_camera_frame = Process(target=camera_frame_func, args=(\"获取摄像头图像\", q_frame, mydict))\n",
    "        proc_frame       = Process(target=proc_frame_func, args=(\"处理图像\", q_frame, q_respond, mydict))\n",
    "        read_rst         = Process(target=read_rst_func, args=(\"播报语音信息\", q_respond))\n",
    "              \n",
    "        # 启动任务\n",
    "        get_camera_frame.start()\n",
    "        proc_frame.start()\n",
    "        read_rst.start()\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        os.remove('tst_sound.wav')\n",
    "        os.remove('camera_pic.jpg')\n",
    "        print(\"任务被终止了\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
